/*
 * ClassVirtualInherit.h
 *
 *  Created on: 2012-8-28
 *      Author: user
 */

#ifndef CLASSVIRTUALINHERIT_H_
#define CLASSVIRTUALINHERIT_H_

#include <iostream>
using namespace std;

class TopV
{
public:
	TopV() {cout << "Top::Top()" << endl;}
	TopV(int r) {a = r;}

	void Func1() {cout << "Top::Func1()" << endl;}
	void topFunc1() {cout << "Top::topFunc1()" << endl;}
public:
	int a;
};

 class LeftV : virtual public TopV
 {
 public:
	 LeftV() {}
	 LeftV(int r)
	 :TopV(r)
	 {b = 11;}

	 void Func1() {cout << "Left::Func1()" << endl;}
	 void leftFunc1() {cout << "Left::leftFunc1()" << endl;}
 public:
    int b;
 };

 class RightV : virtual public TopV
 {
 public:
	 RightV() {}
	 RightV(int r)
	 :TopV(r)
	 {c = 12;}

	 void Func1() {cout << "Right::Func1()" << endl;}
	 void rightFunc1() {cout << "Right::rightFunc1()" << endl;}
 public:
    int c;
 };

 //Memory distribution
 //-------
 //Bottom:
 //--------------------------------               |-----------------------------|
 //|vptr.Left: vtable for Bottom  |  -------->    |vitual base offset: int=20   |
 //|------------------------------|               |-----------------------------|
 //|Left::b                       |               |offset to top: int = 0       | //offset to top means to the beginning of structure
 //|------------------------------|               |-----------------------------|
 //|vptr.Right: vtable for Bottom |----           |typeinfo: typeinfo for Bottom|
 //|------------------------------|    ----       |-----------------------------|
 //|Right::c                      |        -----> |vitual base offset: int=12   | //base offset means to base class offset
 //|------------------------------|               |-----------------------------|
 //|Bottom::d                     |               |offset to top: int = 8       |
 //|------------------------------|               |-----------------------------|
 //|Top::a                        |               |typeinfo: typeinfo for Bottom|
 //|------------------------------|               |-----------------------------|

 // the vtable store the offset to Top

 class BottomV : public LeftV, public RightV
 {
 public:
	 BottomV(int r)
	 :TopV(r), LeftV(r), RightV(r)  //must call the base class TopV construct. As it will construct firstly
	 {d = 13;}

	 void Func1() {cout << "Bottom::Func1()" << endl;}
	 void bottomFunc1() {cout << "Bottom::bottomFunc1()" << endl;}

 public:
    int d;
 };

 class AnotherBottom : public LeftV, public RightV
 {
 public:
 	 void Func1() {cout << "AnotherBottom::Func1()" << endl;}
 	 void anotherBottomFunc1() {cout << "AnotherBottom::anotherBottomFunc1()" << endl;}

  public:
     int e;
 };

 void classVirtualInheritTest()
 {
	 BottomV bt(10); //Top will construct only once

	 cout << "a: " << bt.a << "\tb: " << bt.b << "\tc: " << bt.c << "\td: " << bt.d << endl;

	 BottomV *bottom1 = new BottomV(10);
	 TopV *top1 = bottom1;

	 AnotherBottom *bottom2 = new AnotherBottom();
	 TopV *top2 = bottom2;

	 //LeftV *left = dynamic_cast<LeftV *>(top1); //ambiguous
	 //LeftV *left = static_cast<LeftV *>(top1);  //ambiguous

	// right->Right::Func1() << endl;

	 cout << "Size of Button: " << sizeof(BottomV) << endl;
 }


 class TopV1
 {
 public:
 	TopV1() {cout << "Top1::Top()" << endl;}
 	virtual ~TopV1() {} //has vtable

 	void Func1() {cout << "Top1::Func1()" << endl;}
 	void topFunc1() {cout << "Top1::topFunc1()" << endl;}
 public:
 	int a;
};

 //Memory distribution
    //-------
    //Bottom:
    //--------------------------------               |-----------------------------|
    //|vptr.Left: vtable for Bottom  |  -------->    |vitual base offset: int=8    |
    //|------------------------------|               |-----------------------------|
    //|Left::b                       |               |offset to top: int = 0       |
    //|------------------------------|               |-----------------------------|
    //|vptr.Top: vtable for Bottom   |-----          |typeinfo: typeinfo for Bottom|
    //|------------------------------|     ----      |-----------------------------|
    //|Top::a                        |         ----> |virtual base offset: int = 0 |
    //|------------------------------|               |-----------------------------|
    //                                               |offset to top: int = 8       |
    //                                               |-----------------------------|
    //                                               |typeinfo: typeinfo for Bottom|
    //                                               |_____________________________|
    //                                               |Top::~Top()                  |
    //                                               |-----------------------------|

class LeftV1 : virtual public TopV1
{
public:
	void Func1() {cout << "Left1::Func1()" << endl;}
	void leftFunc1() {cout << "Left1::leftFunc1()" << endl;}

public:
	int b;
};

class RightV1 : virtual public TopV1
{
public:
	void Func1() {cout << "Right1::Func1()" << endl;}
	void rightFunc1() {cout << "Right1::rightFunc1()" << endl;}

public:
	int c;
};


 //Memory distribution
   //-------
   //Bottom:
   //--------------------------------               |-----------------------------|
   //|vptr.Left: vtable for Bottom  |  -------->    |vitual base offset: int=20   |
   //|------------------------------|               |-----------------------------|
   //|Left::b                       |               |offset to top: int = 0       |
   //|------------------------------|               |-----------------------------|
   //|vptr.Right: vtable for Bottom |----           |typeinfo: typeinfo for Bottom|
   //|------------------------------|    ----       |-----------------------------|
   //|Right::c                      |        -----> |vitual base offset: int=12   |
   //|------------------------------|               |-----------------------------|
   //|Bottom::d                     |               |offset to top: int = 8       |
   //|------------------------------|               |-----------------------------|
   //|vptr.Top: vtable for Bottom   |-----          |typeinfo: typeinfo for Bottom|
   //|------------------------------|     ----      |-----------------------------|
   //|Top::a                        |         ----> |virtual base offset: int = 0 |
   //|------------------------------|               |-----------------------------|
   //                                               |offset to top: int = 20      |
   //                                               |-----------------------------|
   //                                               |typeinfo: typeinfo for Bottom|
   //                                               |_____________________________|
   //                                               |Top::~Top()                  |
   //                                               |-----------------------------|

   // the vtable store the offset to Top

class BottomV1 : public LeftV1, public RightV1
{
public:
	void Func1() {cout << "Bottom1::Func1()" << endl;}
	void bottomFunc1() {cout << "Bottom1::bottomFunc1()" << endl;}

	virtual void BottomFunc2() {cout << "Bottom1::bottomFunc2()" << endl;}

public:
	int d;
};

void classVirtualInheritTest1()
{
	cout << "Size of BottomV1: " << sizeof(BottomV1) << endl;
	cout << "Size of LeftV1: " << sizeof(LeftV1) << endl;
	cout << "Size of TopV1: " << sizeof(TopV1) << endl;

	BottomV1 *bottom1 = new BottomV1();
	TopV1 *top1 = bottom1;

	LeftV1 *left = dynamic_cast<LeftV1 *>(top1);

	left->Func1();
	//LeftV *left = static_cast<Left *>(top1);
}

#endif /* CLASSVIRTUALINHERIT_H_ */
